Developed by Hashicorp, creators of Vagrant and Packer, Terraform is a tool that enables us to define our infrastructure as code (formally known as IaC). We can add or modify resources such as computing instances, ssh-keys, network topology or firewall rules and Terraform takes care of generating and performing the necessary operations so the infrastructure provider’s state matches the one described in the code.
Terraform supports a wide range of on-site and cloud infrastructure such as Amazon AWS, Microsoft Azure, Openstack, VMware vSphere and Digital Ocean. A full list of supported providers is located on the tool’s website.
Advantages and disadvantages of using Terraform.
Pros
Infrastructure as code (IaC): This enables us to treat our infrastructure as a file. In plain English this means the following: we can back it up, keep a history of our hardware and configuration (including the associated firewall rules, VLANs and security policies) and rollback changes quickly and efficiently. Our datacenter is stored on a file, thus we can re-deploy our entire infrastructure in a few keystrokes. We are now able to set-up a testing or development environment that is guaranteed to be an exact replica of the actual production environment, or quickly spin-up a second datacenter in a disaster recovery scenario.
Speed: Terraform is fast, very fast. If the infrastructure provider supports it, Terraform parallelizes the generation and modification of resources. The result is: it takes literally a minute to provision one instance, and it takes the exact same time to provision 20 of them.
Supports multiple providers: Unlike Heat or CloudFormation, Terraform supports a variety of providers and can mix and match resources from any of them simultaneously. For example: We could keep the database in our local datacenter to comply with PII regulations, while hosting the frontend of the application somewhere else.
Flexibility: Our infrastructure is declared in .tf files. Terraform consumes all the .tf files from the folder and processes them to create the execution plan. We can separate the resources in a logical way, and easily add/substract a file with new resources for testing purposes.
Cons and caveats
——————————————–
Terraform stores the state of the deployed resources in a local file called terraform.state, and that is the canonical source of truth. If the file is corrupted or the state described in it no longer matches the deployed infrastructure (for example, a remote resource is modified manually), Terraform will fix the discrepancy by destroying the remote resource and recreating it according to the local definition.
Terraform depends entirely on the provider’s API: The tool tries to mitigate potential failures by retrying and verifying API calls. Inconsistencies on the provider side can cause a situation in which Terraform is not able to match a specific remote resource to its local definition of said resource, thus generating an execution plan that destroys the remote resource and then creates another instance according to the local .tf files.
The declarative sintax of the .tf files is provider-specific. That means we will need to rewrite the definition of our infrastructure if we were to switch providers.
Command overview.
There are four basic commands that you must know to work with Terraform: refresh, plan, apply and destroy. Refresh updates the terraform.state file to match the provider’s state, plan outputs the changes that would be applied and apply performs the changes. Destroy does what you would expect: destroys the remote resources.
Apply does not prompt for confirmation. Any discrepancy between the remote state and the local definition will be fixed irreversibly. It’s important to double-check the plan to make sure it matches our expectations.
Installing Terraform
Terraform is available for a variety of operating systems, though we’ll use Ubuntu throughout this post. While it could be available on the repositories of your favourite OS, there are no guarantees it will be up to date. The latest version can be downloaded from its website.
It does not need to be installed, unpacking the downloaded file is all that is required.
First steps: Creating an instance on Amazon AWS.
The objective is to deploy Ubuntu 16.04 on a t2.micro instance, with as little configuration as possible to enable SSH connections.
To enable Terraform to communicate with the remote provider, we will need API keys. In the case of Amazon AWS, they can be obtained from the console.
What follows is the instance.tf file we are going to use.
Inspecting the generated plan, we can clearly see that the above operations are going to be performed.
Note: this plan is not saved anywhere, and only exists in memory at this time. When using apply , Terraform will generate the plan again and it might be different if circumstances have changed.
The plan can be saved to disk using the -out switch, and apply can be instructed to load the plan from a file instead of generating it at runtime.
Let’s apply the plan.
Now we can inspect the state of our infrastructure using terraform show. Among other things, it shows us the public IP of the newly created instance.
Let’s delete this instance with the destroy command.
Basic provisioning of instances.
Terraform can transfer files and folders to the newly created instance, and it provides a number of facilities to execute software remotely. Using the remote-exec directive, we are going to deploy a script that writes “Hello” to a file in the /tmp/ folder.
The script will be called bootstrap.sh, and these are its contents.
We modify the instance definition to add the provisioner directive, and the SSH it will use to remotely login to the instance.
After applying the plan, we can see that Terraform has logged-in to the instance and executed the script.
And after logging in manually ourselves, we can verify that it did run the script correctly.
In a future post we will explore how to use this functionality to provision instances automatically.